package org.xs.web.http.validate;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.ho.yaml.Yaml;
import org.springframework.beans.factory.InitializingBean;
import org.xs.web.util.Helpers;
import org.xs.web.util.Resources;

public class ValidateRule implements InitializingBean{
	private static final Logger logger = Logger.getLogger(ValidateRule.class);
	
	private String[] validateClass = new String[]{"org.xs.web.http.validate.Validators"};
	private String[] validateFiles = new String[]{"validate.yml"};
	
	
	
	public void init(){
		for(String name:validateFiles){
			URL url = Resources.getResource(name);
			if(url != null){
				ValidateExecutor.addValidateMap(
						new ValidateMap(name, new File(url.getFile()), 
						this,loadValidate( new File(url.getFile()))));
			}
		}
	}
	
	public List<ValidateEntry> loadValidate(File name){
		List<ValidateEntry> validateEntries = new ArrayList<ValidateEntry>();
		FileReader reader=null;
		try {
			reader = new FileReader(name);
			Map<String,Object> validates = (Map<String, Object>) Yaml.load(reader);
			Map<String,Object> contrs = null;
			String[] ca = null;
			String temp = null;
			ValidateEntry entry = null;
			
			for(Map.Entry<String, Object> validate : validates.entrySet()){
				temp = (String)validate.getKey();
				ca = temp.split("_");
				if(ca.length >0){
					if(ca.length == 2){
						entry = new ValidateEntry(ca[0], ca[1]);
					}else{
						entry = new ValidateEntry("",ca[0]);
					}
				}
				contrs = (Map<String, Object>) validate.getValue();
				for(Map.Entry<String, Object> field: contrs.entrySet()){
					entry.addField(field.getKey(),extructMethod(String.valueOf(field.getValue())));
				}
				 
				validateEntries.add(entry);
			}
			return validateEntries;
		} catch (FileNotFoundException e1) {
			throw new RuntimeException(e1);
		}finally{
			if(reader != null)
				try {
					reader.close();
				} catch (IOException e) {
					 
				}
		}
	}
	
	public ValidateMethod[] extructMethod(String values){
		String[] ms = values.split("\\s+");
		ValidateMethod[] methods = new ValidateMethod[ms.length];
		String method=null;
		String[] args=null;
		String msg=null;
		
		int pos=0;
		int len=0;
		int pIn=0,pOut=0,pMsg=0;
		String argStr = null;
		int i =0;
		for(String m : ms){
			len=m.length();
			pos=0;
			while(pos < len){
				char ch = m.charAt(pos);
				if(ch == '('){
					pos += 1;
					pIn = pos;
				}else if(ch == ')'){
					pOut = pos;
					pos +=1;
				}else if(ch == '=' && pos +1 < len){
					pos += 1;
					ch = m.charAt(pos);
					if(ch == '>'){
						pos +=1;
						pMsg = pos;
					}
				}else{
					pos +=1;
				}
			}
		 
			method = m;
			if(pIn >0){
				method = m.substring(0,pIn - 1);
				argStr = m.substring(pIn,pOut);
				args = argStr.split(",");
			}
			if(pMsg > 0){
				if(pIn <= 0){
					method = method.substring(0,pMsg - 2);
					method = method.trim();
				}
				msg = m.substring(pMsg,m.length());
			}
			Object[] mAndObj = getMethod(method);
			methods[i] = new ValidateMethod(
						method,
						mAndObj == null ? null : (Method)mAndObj[0], 
						mAndObj == null ? null : mAndObj[1],
						msg, args);
			i++;
		}
		
		return methods;
	}
	
	
	public Object[] getMethod(String name){
		Object[] res = new Object[2];
		Class<?> clazz = null;
		for(String className: validateClass){
			try {
				clazz = Class.forName(className);
				for(Method md : clazz.getDeclaredMethods()){
					if(name.equalsIgnoreCase(md.getName())){
						res[0] = md;
						res[1] = clazz.newInstance();
						return res;
					}
				}
			} catch (ClassNotFoundException e) {
				logger.debug("class not found "+e);
			} catch (InstantiationException e) {
				logger.debug("new instance class "+e);
			} catch (IllegalAccessException e) {
				logger.debug("new instance class "+e);
			}
			
		}
		logger.debug("validate method "+ name +" dose not exists in class: "+ Helpers.join(validateClass));
		return null;
	}
	
	
	public void setValidateClass(String[] validateClass) {
		this.validateClass = validateClass;
	}

	 

	public void setValidateFiles(String[] validateFiles) {
		this.validateFiles = validateFiles;
	}

	public static void main(String[] args) {
		Map<String,Object> form = new HashMap<String, Object>();
		form.put("username", "实时");
		form.put("password", "");
		new ValidateRule().init();
		ValidateExecutor.validate("abc", "bbb",form);
		 
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		init();
	}
}
